home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / sv_send.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  12.9 KB  |  568 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // sv_main.c -- server main program
  21.  
  22. #include "server.h"
  23.  
  24. /*
  25. =============================================================================
  26.  
  27. Com_Printf redirection
  28.  
  29. =============================================================================
  30. */
  31.  
  32. char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
  33.  
  34. void SV_FlushRedirect (int sv_redirected, char *outputbuf)
  35. {
  36.     if (sv_redirected == RD_PACKET)
  37.     {
  38.         Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", outputbuf);
  39.     }
  40.     else if (sv_redirected == RD_CLIENT)
  41.     {
  42.         MSG_WriteByte (&sv_client->netchan.message, svc_print);
  43.         MSG_WriteByte (&sv_client->netchan.message, PRINT_HIGH);
  44.         MSG_WriteString (&sv_client->netchan.message, outputbuf);
  45.     }
  46. }
  47.  
  48.  
  49. /*
  50. =============================================================================
  51.  
  52. EVENT MESSAGES
  53.  
  54. =============================================================================
  55. */
  56.  
  57.  
  58. /*
  59. =================
  60. SV_ClientPrintf
  61.  
  62. Sends text across to be displayed if the level passes
  63. =================
  64. */
  65. void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
  66. {
  67.     va_list        argptr;
  68.     char        string[1024];
  69.     
  70.     if (level < cl->messagelevel)
  71.         return;
  72.     
  73.     va_start (argptr,fmt);
  74.     vsprintf (string, fmt,argptr);
  75.     va_end (argptr);
  76.     
  77.     MSG_WriteByte (&cl->netchan.message, svc_print);
  78.     MSG_WriteByte (&cl->netchan.message, level);
  79.     MSG_WriteString (&cl->netchan.message, string);
  80. }
  81.  
  82. /*
  83. =================
  84. SV_BroadcastPrintf
  85.  
  86. Sends text to all active clients
  87. =================
  88. */
  89. void SV_BroadcastPrintf (int level, char *fmt, ...)
  90. {
  91.     va_list        argptr;
  92.     char        string[2048];
  93.     client_t    *cl;
  94.     int            i;
  95.  
  96.     va_start (argptr,fmt);
  97.     vsprintf (string, fmt,argptr);
  98.     va_end (argptr);
  99.     
  100.     // echo to console
  101.     if (dedicated->value)
  102.     {
  103.         char    copy[1024];
  104.         int        i;
  105.         
  106.         // mask off high bits
  107.         for (i=0 ; i<1023 && string[i] ; i++)
  108.             copy[i] = string[i]&127;
  109.         copy[i] = 0;
  110.         Com_Printf ("%s", copy);
  111.     }
  112.  
  113.     for (i=0, cl = svs.clients ; i<maxclients->value; i++, cl++)
  114.     {
  115.         if (level < cl->messagelevel)
  116.             continue;
  117.         if (cl->state != cs_spawned)
  118.             continue;
  119.         MSG_WriteByte (&cl->netchan.message, svc_print);
  120.         MSG_WriteByte (&cl->netchan.message, level);
  121.         MSG_WriteString (&cl->netchan.message, string);
  122.     }
  123. }
  124.  
  125. /*
  126. =================
  127. SV_BroadcastCommand
  128.  
  129. Sends text to all active clients
  130. =================
  131. */
  132. void SV_BroadcastCommand (char *fmt, ...)
  133. {
  134.     va_list        argptr;
  135.     char        string[1024];
  136.     
  137.     if (!sv.state)
  138.         return;
  139.     va_start (argptr,fmt);
  140.     vsprintf (string, fmt,argptr);
  141.     va_end (argptr);
  142.  
  143.     MSG_WriteByte (&sv.multicast, svc_stufftext);
  144.     MSG_WriteString (&sv.multicast, string);
  145.     SV_Multicast (NULL, MULTICAST_ALL_R);
  146. }
  147.  
  148.  
  149. /*
  150. =================
  151. SV_Multicast
  152.  
  153. Sends the contents of sv.multicast to a subset of the clients,
  154. then clears sv.multicast.
  155.  
  156. MULTICAST_ALL    same as broadcast (origin can be NULL)
  157. MULTICAST_PVS    send to clients potentially visible from org
  158. MULTICAST_PHS    send to clients potentially hearable from org
  159. =================
  160. */
  161. void SV_Multicast (vec3_t origin, multicast_t to)
  162. {
  163.     client_t    *client;
  164.     byte        *mask;
  165.     int            leafnum, cluster;
  166.     int            j;
  167.     qboolean    reliable;
  168.     int            area1, area2;
  169.  
  170.     reliable = false;
  171.  
  172.     if (to != MULTICAST_ALL_R && to != MULTICAST_ALL)
  173.     {
  174.         leafnum = CM_PointLeafnum (origin);
  175.         area1 = CM_LeafArea (leafnum);
  176.     }
  177.     else
  178.     {
  179.         leafnum = 0;    // just to avoid compiler warnings
  180.         area1 = 0;
  181.     }
  182.  
  183.     // if doing a serverrecord, store everything
  184.     if (svs.demofile)
  185.         SZ_Write (&svs.demo_multicast, sv.multicast.data, sv.multicast.cursize);
  186.     
  187.     switch (to)
  188.     {
  189.     case MULTICAST_ALL_R:
  190.         reliable = true;    // intentional fallthrough
  191.     case MULTICAST_ALL:
  192.         leafnum = 0;
  193.         mask = NULL;
  194.         break;
  195.  
  196.     case MULTICAST_PHS_R:
  197.         reliable = true;    // intentional fallthrough
  198.     case MULTICAST_PHS:
  199.         leafnum = CM_PointLeafnum (origin);
  200.         cluster = CM_LeafCluster (leafnum);
  201.         mask = CM_ClusterPHS (cluster);
  202.         break;
  203.  
  204.     case MULTICAST_PVS_R:
  205.         reliable = true;    // intentional fallthrough
  206.     case MULTICAST_PVS:
  207.         leafnum = CM_PointLeafnum (origin);
  208.         cluster = CM_LeafCluster (leafnum);
  209.         mask = CM_ClusterPVS (cluster);
  210.         break;
  211.  
  212.     default:
  213.         mask = NULL;
  214.         Com_Error (ERR_FATAL, "SV_Multicast: bad to:%i", to);
  215.     }
  216.  
  217.     // send the data to all relevent clients
  218.     for (j = 0, client = svs.clients; j < maxclients->value; j++, client++)
  219.     {
  220.         if (client->state == cs_free || client->state == cs_zombie)
  221.             continue;
  222.         if (client->state != cs_spawned && !reliable)
  223.             continue;
  224.  
  225.         if (mask)
  226.         {
  227.             leafnum = CM_PointLeafnum (client->edict->s.origin);
  228.             cluster = CM_LeafCluster (leafnum);
  229.             area2 = CM_LeafArea (leafnum);
  230.             if (!CM_AreasConnected (area1, area2))
  231.                 continue;
  232.             if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
  233.                 continue;
  234.         }
  235.  
  236.         if (reliable)
  237.             SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize);
  238.         else
  239.             SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
  240.     }
  241.  
  242.     SZ_Clear (&sv.multicast);
  243. }
  244.  
  245.  
  246. /*  
  247. ==================
  248. SV_StartSound
  249.  
  250. Each entity can have eight independant sound sources, like voice,
  251. weapon, feet, etc.
  252.  
  253. If cahnnel & 8, the sound will be sent to everyone, not just
  254. things in the PHS.
  255.  
  256. FIXME: if entity isn't in PHS, they must be forced to be sent or
  257. have the origin explicitly sent.
  258.  
  259. Channel 0 is an auto-allocate channel, the others override anything
  260. already running on that entity/channel pair.
  261.  
  262. An attenuation of 0 will play full volume everywhere in the level.
  263. Larger attenuations will drop off.  (max 4 attenuation)
  264.  
  265. Timeofs can range from 0.0 to 0.1 to cause sounds to be started
  266. later in the frame than they normally would.
  267.  
  268. If origin is NULL, the origin is determined from the entity origin
  269. or the midpoint of the entity box for bmodels.
  270. ==================
  271. */  
  272. void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
  273.                     int soundindex, float volume,
  274.                     float attenuation, float timeofs)
  275. {       
  276.     int            sendchan;
  277.     int            flags;
  278.     int            i;
  279.     int            ent;
  280.     vec3_t        origin_v;
  281.     qboolean    use_phs;
  282.  
  283.     if (volume < 0 || volume > 1.0)
  284.         Com_Error (ERR_FATAL, "SV_StartSound: volume = %f", volume);
  285.  
  286.     if (attenuation < 0 || attenuation > 4)
  287.         Com_Error (ERR_FATAL, "SV_StartSound: attenuation = %f", attenuation);
  288.  
  289. //    if (channel < 0 || channel > 15)
  290. //        Com_Error (ERR_FATAL, "SV_StartSound: channel = %i", channel);
  291.  
  292.     if (timeofs < 0 || timeofs > 0.255)
  293.         Com_Error (ERR_FATAL, "SV_StartSound: timeofs = %f", timeofs);
  294.  
  295.     ent = NUM_FOR_EDICT(entity);
  296.  
  297.     if (channel & 8)    // no PHS flag
  298.     {
  299.         use_phs = false;
  300.         channel &= 7;
  301.     }
  302.     else
  303.         use_phs = true;
  304.  
  305.     sendchan = (ent<<3) | (channel&7);
  306.  
  307.     flags = 0;
  308.     if (volume != DEFAULT_SOUND_PACKET_VOLUME)
  309.         flags |= SND_VOLUME;
  310.     if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
  311.         flags |= SND_ATTENUATION;
  312.  
  313.     // the client doesn't know that bmodels have weird origins
  314.     // the origin can also be explicitly set
  315.     if ( (entity->svflags & SVF_NOCLIENT)
  316.         || (entity->solid == SOLID_BSP) 
  317.         || origin )
  318.         flags |= SND_POS;
  319.  
  320.     // always send the entity number for channel overrides
  321.     flags |= SND_ENT;
  322.  
  323.     if (timeofs)
  324.         flags |= SND_OFFSET;
  325.  
  326.     // use the entity origin unless it is a bmodel or explicitly specified
  327.     if (!origin)
  328.     {
  329.         origin = origin_v;
  330.         if (entity->solid == SOLID_BSP)
  331.         {
  332.             for (i=0 ; i<3 ; i++)
  333.                 origin_v[i] = entity->s.origin[i]+0.5*(entity->mins[i]+entity->maxs[i]);
  334.         }
  335.         else
  336.         {
  337.             VectorCopy (entity->s.origin, origin_v);
  338.         }
  339.     }
  340.  
  341.     MSG_WriteByte (&sv.multicast, svc_sound);
  342.     MSG_WriteByte (&sv.multicast, flags);
  343.     MSG_WriteByte (&sv.multicast, soundindex);
  344.  
  345.     if (flags & SND_VOLUME)
  346.         MSG_WriteByte (&sv.multicast, volume*255);
  347.     if (flags & SND_ATTENUATION)
  348.         MSG_WriteByte (&sv.multicast, attenuation*64);
  349.     if (flags & SND_OFFSET)
  350.         MSG_WriteByte (&sv.multicast, timeofs*1000);
  351.  
  352.     if (flags & SND_ENT)
  353.         MSG_WriteShort (&sv.multicast, sendchan);
  354.  
  355.     if (flags & SND_POS)
  356.         MSG_WritePos (&sv.multicast, origin);
  357.  
  358.     // if the sound doesn't attenuate,send it to everyone
  359.     // (global radio chatter, voiceovers, etc)
  360.     if (attenuation == ATTN_NONE)
  361.         use_phs = false;
  362.  
  363.     if (channel & CHAN_RELIABLE)
  364.     {
  365.         if (use_phs)
  366.             SV_Multicast (origin, MULTICAST_PHS_R);
  367.         else
  368.             SV_Multicast (origin, MULTICAST_ALL_R);
  369.     }
  370.     else
  371.     {
  372.         if (use_phs)
  373.             SV_Multicast (origin, MULTICAST_PHS);
  374.         else
  375.             SV_Multicast (origin, MULTICAST_ALL);
  376.     }
  377. }           
  378.  
  379.  
  380. /*
  381. ===============================================================================
  382.  
  383. FRAME UPDATES
  384.  
  385. ===============================================================================
  386. */
  387.  
  388.  
  389.  
  390. /*
  391. =======================
  392. SV_SendClientDatagram
  393. =======================
  394. */
  395. qboolean SV_SendClientDatagram (client_t *client)
  396. {
  397.     byte        msg_buf[MAX_MSGLEN];
  398.     sizebuf_t    msg;
  399.  
  400.     SV_BuildClientFrame (client);
  401.  
  402.     SZ_Init (&msg, msg_buf, sizeof(msg_buf));
  403.     msg.allowoverflow = true;
  404.  
  405.     // send over all the relevant entity_state_t
  406.     // and the player_state_t
  407.     SV_WriteFrameToClient (client, &msg);
  408.  
  409.     // copy the accumulated multicast datagram
  410.     // for this client out to the message
  411.     // it is necessary for this to be after the WriteEntities
  412.     // so that entity references will be current
  413.     if (client->datagram.overflowed)
  414.         Com_Printf ("WARNING: datagram overflowed for %s\n", client->name);
  415.     else
  416.         SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
  417.     SZ_Clear (&client->datagram);
  418.  
  419.     if (msg.overflowed)
  420.     {    // must have room left for the packet header
  421.         Com_Printf ("WARNING: msg overflowed for %s\n", client->name);
  422.         SZ_Clear (&msg);
  423.     }
  424.  
  425.     // send the datagram
  426.     Netchan_Transmit (&client->netchan, msg.cursize, msg.data);
  427.  
  428.     // record the size for rate estimation
  429.     client->message_size[sv.framenum % RATE_MESSAGES] = msg.cursize;
  430.  
  431.     return true;
  432. }
  433.  
  434.  
  435. /*
  436. ==================
  437. SV_DemoCompleted
  438. ==================
  439. */
  440. void SV_DemoCompleted (void)
  441. {
  442.     if (sv.demofile)
  443.     {
  444.         fclose (sv.demofile);
  445.         sv.demofile = NULL;
  446.     }
  447.     SV_Nextserver ();
  448. }
  449.  
  450.  
  451. /*
  452. =======================
  453. SV_RateDrop
  454.  
  455. Returns true if the client is over its current
  456. bandwidth estimation and should not be sent another packet
  457. =======================
  458. */
  459. qboolean SV_RateDrop (client_t *c)
  460. {
  461.     int        total;
  462.     int        i;
  463.  
  464.     // never drop over the loopback
  465.     if (c->netchan.remote_address.type == NA_LOOPBACK)
  466.         return false;
  467.  
  468.     total = 0;
  469.  
  470.     for (i = 0 ; i < RATE_MESSAGES ; i++)
  471.     {
  472.         total += c->message_size[i];
  473.     }
  474.  
  475.     if (total > c->rate)
  476.     {
  477.         c->surpressCount++;
  478.         c->message_size[sv.framenum % RATE_MESSAGES] = 0;
  479.         return true;
  480.     }
  481.  
  482.     return false;
  483. }
  484.  
  485. /*
  486. =======================
  487. SV_SendClientMessages
  488. =======================
  489. */
  490. void SV_SendClientMessages (void)
  491. {
  492.     int            i;
  493.     client_t    *c;
  494.     int            msglen;
  495.     byte        msgbuf[MAX_MSGLEN];
  496.     int            r;
  497.  
  498.     msglen = 0;
  499.  
  500.     // read the next demo message if needed
  501.     if (sv.state == ss_demo && sv.demofile)
  502.     {
  503.         if (sv_paused->value)
  504.             msglen = 0;
  505.         else
  506.         {
  507.             // get the next message
  508.             r = fread (&msglen, 4, 1, sv.demofile);
  509.             if (r != 1)
  510.             {
  511.                 SV_DemoCompleted ();
  512.                 return;
  513.             }
  514.             msglen = LittleLong (msglen);
  515.             if (msglen == -1)
  516.             {
  517.                 SV_DemoCompleted ();
  518.                 return;
  519.             }
  520.             if (msglen > MAX_MSGLEN)
  521.                 Com_Error (ERR_DROP, "SV_SendClientMessages: msglen > MAX_MSGLEN");
  522.             r = fread (msgbuf, msglen, 1, sv.demofile);
  523.             if (r != 1)
  524.             {
  525.                 SV_DemoCompleted ();
  526.                 return;
  527.             }
  528.         }
  529.     }
  530.  
  531.     // send a message to each connected client
  532.     for (i=0, c = svs.clients ; i<maxclients->value; i++, c++)
  533.     {
  534.         if (!c->state)
  535.             continue;
  536.         // if the reliable message overflowed,
  537.         // drop the client
  538.         if (c->netchan.message.overflowed)
  539.         {
  540.             SZ_Clear (&c->netchan.message);
  541.             SZ_Clear (&c->datagram);
  542.             SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name);
  543.             SV_DropClient (c);
  544.         }
  545.  
  546.         if (sv.state == ss_cinematic 
  547.             || sv.state == ss_demo 
  548.             || sv.state == ss_pic
  549.             )
  550.             Netchan_Transmit (&c->netchan, msglen, msgbuf);
  551.         else if (c->state == cs_spawned)
  552.         {
  553.             // don't overrun bandwidth
  554.             if (SV_RateDrop (c))
  555.                 continue;
  556.  
  557.             SV_SendClientDatagram (c);
  558.         }
  559.         else
  560.         {
  561.     // just update reliable    if needed
  562.             if (c->netchan.message.cursize    || curtime - c->netchan.last_sent > 1000 )
  563.                 Netchan_Transmit (&c->netchan, 0, NULL);
  564.         }
  565.     }
  566. }
  567.  
  568.